package cn.exrick.xboot.modules.content.controller;

import cn.exrick.xboot.common.constant.CommonConstant;
import cn.exrick.xboot.common.exception.XbootException;
import cn.exrick.xboot.common.redis.RedisTemplateHelper;
import cn.exrick.xboot.common.utils.*;
import cn.exrick.xboot.common.vo.Result;
import cn.exrick.xboot.config.properties.RestTemplateProperties;
import cn.exrick.xboot.modules.base.entity.Department;
import cn.exrick.xboot.modules.base.entity.User;
import cn.exrick.xboot.modules.content.entity.*;
import cn.exrick.xboot.modules.content.entity.HontVo.HontRoleLevelVo;
import cn.exrick.xboot.modules.content.service.*;
import cn.exrick.xboot.modules.content.service.mybatis.IHontUserRoleService;
import cn.hutool.core.util.StrUtil;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.reflect.TypeToken;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheConfig;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.bind.annotation.*;

import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;


/**
 * @author Exrick
 */
@Slf4j
@RestController
@Api(description = "部门管理接口")
@RequestMapping("/xboot/hontDepartment")
@CacheConfig(cacheNames = "hontDepartment")
@Transactional
public class HontDepartmentController{

    @Autowired
    private HontDepartmentService hontDepartmentService;
    @Autowired
    private HontDepartmentHeaderService hontDepartmentHeaderService;
    @Autowired
    private HontUserService hontUserService;
    @Autowired
    private HontRoleDepartmentService hontRoleDepartmentService;
    @Autowired
    private SecurityUtil securityUtil;
    @Autowired
    private StringRedisTemplate redisTemplate;
    @Autowired
    private RestTemplateProperties restTemplateProperties;
    @Autowired
    private HontRoleService hontRoleService;

    @Autowired
    private RedisTemplateHelper redisTemplateHelper;

    @RequestMapping(value = "/departmentTree",method = RequestMethod.GET)
    @ApiOperation(value = "部门tree")
    public Result<List<HontDepartment>> departmentTree(){
        List<HontDepartment> content=hontDepartmentService.departmentTree();
        return new ResultUtil<List<HontDepartment>>().setData(content);
    }
    @RequestMapping(value = "/getByParentId/{parentId}",method = RequestMethod.GET)
    @ApiOperation(value = "通过id获取")
    public Result<List<HontDepartment>> getByParentId(@PathVariable String parentId,
                                                  @ApiParam("是否开始数据权限过滤") @RequestParam(required = false, defaultValue = "true") Boolean openDataFilter){

        List<HontDepartment> list;
        HontUser u = securityUtil.getCurrUser();
        String key = "hontDepartment::"+parentId+":"+u.getId()+"_"+openDataFilter;
        String v = redisTemplate.opsForValue().get(key);
        if(StrUtil.isNotBlank(v)){
            list = new Gson().fromJson(v, new TypeToken<List<Department>>(){}.getType());
            return new ResultUtil<List<HontDepartment>>().setData(list);
        }
        list = hontDepartmentService.findByParentIdOrderBySortOrder(parentId, openDataFilter);
        list = setInfo(list);
        redisTemplate.opsForValue().set(key,
                new GsonBuilder().registerTypeAdapterFactory(HibernateProxyTypeAdapter.FACTORY).create().toJson(list), 15L, TimeUnit.DAYS);
        return new ResultUtil<List<HontDepartment>>().setData(list);
    }
    @RequestMapping(value = "/add",method = RequestMethod.POST)
    @ApiOperation(value = "添加")
    public Result<Object> add(HontDepartment department){
        HontDepartment byTitle = hontDepartmentService.findByTitle(department.getTitle());
        String parentId = department.getParentId();
        if (byTitle != null){
            return ResultUtil.error("该部门已存在");
        }
        List<HontDepartment> byParentIdOrderBySortOrder = hontDepartmentService.findByParentIdOrderBySortOrder(parentId);
        int nextSortOrder = byParentIdOrderBySortOrder.size() + 1;
        String id;
        if(CommonConstant.PARENT_ID.equals(parentId)){
            id = String.format("%02d", nextSortOrder);
        }else{
            HontDepartment parent = hontDepartmentService.get(parentId);
            String sortOrderStr = String.format("%02d", nextSortOrder);
            id = parentId + sortOrderStr;
            if(parent.getIsParent()==null || !parent.getIsParent()){
                parent.setIsParent(true);
                hontDepartmentService.update(parent);
                // 更新上级节点的缓存
                Set<String> keysParent = redisTemplateHelper.keys("hontDepartment::"+parent.getParentId()+":*");
                redisTemplate.delete(keysParent);
            }
        }
        department.setId(id);
        HontDepartment d = hontDepartmentService.save(department);
        // 同步该节点缓存
        HontUser u = securityUtil.getCurrUser();
        Set<String> keys = redisTemplateHelper.keys("hontDepartment::"+department.getParentId()+":*");
        redisTemplate.delete(keys);
        if (d == null){
            return ResultUtil.success("添加失败");
        }
        return ResultUtil.success("添加成功");
    }
    @RequestMapping(value = "/edit",method = RequestMethod.POST)
    @ApiOperation(value = "编辑")
    public Result<Object> edit(HontDepartment department,
                               @RequestParam(required = false) String[] mainHeader,
                               @RequestParam(required = false) String[] viceHeader) throws Exception {
        HontDepartment hontDepartment = hontDepartmentService.get(department.getId());
        Boolean oldParent = hontDepartment.getIsParent();
        department.setIsParent(oldParent);
        HontDepartment d = hontDepartmentService.update(department);
        // 先删除原数据
        hontDepartmentHeaderService.deleteByHontDepartmentId(department.getId());
        for(String id:mainHeader){
            HontDepartmentHeader dh = new HontDepartmentHeader();
            dh.setHontUserId(id);
            dh.setHontDepartmentId(d.getId());
            dh.setType(CommonConstant.HEADER_TYPE_MAIN);
            hontDepartmentHeaderService.save(dh);
        }
        for(String id:viceHeader){
            HontDepartmentHeader dh = new HontDepartmentHeader();
            dh.setHontUserId(id);
            dh.setHontDepartmentId(d.getId());
            dh.setType(CommonConstant.HEADER_TYPE_VICE);
            hontDepartmentHeaderService.save(dh);
        }

        return ResultUtil.success("编辑成功");
    }
    @RequestMapping(value = "/delByIds/{ids}",method = RequestMethod.DELETE)
    @ApiOperation(value = "批量通过id删除")
    public Result<Object> delByIds(@PathVariable String[] ids){

        for(String id : ids){
            deleteRecursion(id, ids);
        }
        // 手动删除所有部门缓存
        Set<String> keys = redisTemplateHelper.keys("hontDepartment:" + "*");
        redisTemplate.delete(keys);
        // 删除数据权限缓存
        Set<String> keysUserRoleData = redisTemplateHelper.keys("hontUserRole::depIds:" + "*");
        redisTemplate.delete(keysUserRoleData);
        return ResultUtil.success("批量通过id删除数据成功");
    }
    public void deleteRecursion(String id, String[] ids) {

        List<HontUser> list = hontUserService.findByDepartmentId(id);
        if (list != null && list.size() > 0) {
            throw new XbootException("删除失败，包含正被用户使用关联的部门");
        }
        // 获得其父节点
        HontDepartment dep = hontDepartmentService.get(id);
        HontDepartment parent = null;
        if (dep != null && StrUtil.isNotBlank(dep.getParentId())) {
            parent = hontDepartmentService.get(dep.getParentId());
        }
        hontDepartmentService.delete(id);
        // 删除关联数据权限
        hontRoleDepartmentService.deleteByHontDepartmentId(id);
        // 删除关联部门负责人
        hontDepartmentHeaderService.deleteByHontDepartmentId(id);
        // 判断父节点是否还有子节点
        if (parent != null) {
            List<HontDepartment> childrenDeps = hontDepartmentService.findByParentIdOrderBySortOrder(parent.getId(), false);
            if (childrenDeps == null || childrenDeps.size() == 0) {
                parent.setIsParent(false);
                hontDepartmentService.update(parent);
            }
        }
        // 递归删除
        List<HontDepartment> departments = hontDepartmentService.findByParentIdOrderBySortOrder(id, false);
        for (HontDepartment d : departments) {
            if (!CommonUtil.judgeIds(d.getId(), ids)) {
                deleteRecursion(d.getId(), ids);
            }
        }
    }


    @RequestMapping(value = "/getAllList",method = RequestMethod.GET)
    @ApiOperation(value = "获取全部部门")
    public Result<Object> roleGetAll(){
        List<HontDepartment> list = hontDepartmentService.getAll();
        return ResultUtil.data(list);
    }
    /*
    * 获取所有班组 parent
    * */
    @RequestMapping(value = "/getAllTeamList",method = RequestMethod.GET)
    @ApiOperation(value = "获取全部部门")
    public Result<Object> getAllTeamList(){

       List<HontDepartment> list=hontDepartmentService.getAllTeamList();
        return ResultUtil.data(list);
    }

    @RequestMapping(value = "/search",method = RequestMethod.GET)
    @ApiOperation(value = "部门名模糊搜索")
    public Result<List<HontDepartment>> searchByTitle(@RequestParam String title){

        List<HontDepartment> list = hontDepartmentService.findByTitleLikeOrder("%"+title+"%");
        //list = setInfo(list);
        return new ResultUtil<List<HontDepartment>>().setData(list);
    }

    public List<HontDepartment> setInfo(List<HontDepartment> list){

        // lambda表达式
        list.forEach(item -> {
            if(!CommonConstant.PARENT_ID.equals(item.getParentId())){
                HontDepartment parent = hontDepartmentService.get(item.getParentId());
                item.setParentTitle(parent.getTitle());
            }else{
                item.setParentTitle("一级部门");
            }
            // 设置负责人
            item.setMainHeader(hontDepartmentHeaderService.findHeaderByHontDepartmentId(item.getId(), CommonConstant.HEADER_TYPE_MAIN));
            item.setViceHeader(hontDepartmentHeaderService.findHeaderByHontDepartmentId(item.getId(), CommonConstant.HEADER_TYPE_VICE));
        });
        return list;
    }

    @RequestMapping(value = "/departmentAndHontUserTree",method = RequestMethod.GET)
    @ApiOperation(value = "部门tree带人员")
    public Result<List<HontDepartment>> departmentAndHontUserTree(){
        List<HontUser> byApprove = hontUserService.findByApprove(CommonConstant.PASS);
        List<HontRoleLevelVo> roleLevelById = hontRoleService.findRoleLevelById();
        byApprove = byApprove.stream().map(m -> {
            roleLevelById.stream().filter(m2-> Objects.equals(m.getId(),m2.getId())).forEach(m2-> {
                m.setRoleLevel(m2.getRoleLevel());
            });
            return m;
        }).collect(Collectors.toList());

        List<HontDepartment> list = hontDepartmentService.findByParentIdOrderBySortOrder("0", false);
        for(int i=0;i<list.size();i++) {
            List<HontDepartment> departments = cheldrenDepartment(list.get(i).getId(),byApprove);
            String departId = list.get(i).getId();
            List<HontUser> hontUserList = byApprove.stream().filter(hontUser -> hontUser.getDepartmentId().equals(departId)).collect(Collectors.toList());
            if (departments.size() > 0) {
                list.get(i).setChildrenDepartment(departments);
                list.get(i).setChildrenUser(hontUserList);
            }else if (hontUserList.size() > 0){
                list.get(i).setChildrenUser(hontUserList);
                list.get(i).setChildrenDepartment(new ArrayList<>());
            }else {
                list.get(i).setChildrenDepartment(new ArrayList<>());
            }
        }
        return new ResultUtil<List<HontDepartment>>().setData(list);
    }

    public List<HontDepartment> cheldrenDepartment(String id,List<HontUser> hontUsers){
        List<HontDepartment> list = hontDepartmentService.findByParentIdOrderBySortOrder(id, false);

        for(int i=0;i<list.size();i++) {
            List<HontDepartment> departments = cheldrenDepartment(list.get(i).getId(),hontUsers);
            String departId = list.get(i).getId();
            List<HontUser> hontUserList = hontUsers.stream().filter(hontUser -> hontUser.getDepartmentId().equals(departId)).collect(Collectors.toList());
            if (departments.size() > 0) {
                list.get(i).setChildrenDepartment(departments);
                list.get(i).setChildrenUser(hontUserList);
            }else if (hontUserList.size() > 0){
                list.get(i).setChildrenUser(hontUserList);
                list.get(i).setChildrenDepartment(new ArrayList<>());
            }else {
                list.get(i).setChildrenDepartment(new ArrayList<>());
            }
        }
//        for(int i=0;i<content.size();i++){
//            String id = content.get(i).getId();
//            List<HontUser> hontUserList = hontUsers.stream().filter(hontUser -> hontUser.getDepartmentId().equals(id)).collect(Collectors.toList());
//            content.get(i).setChildrenUser(hontUserList);
//        }
        return list;
    }
}
